﻿using System;
using System.ComponentModel.Composition;
using Autofac;
using Autofac.Builder;
using AutofacContrib.CommonServiceLocator;
using Microsoft.Practices.ServiceLocation;
using Mockery.Core.CommonContainer;

namespace CommonContainer.Autofac
{
    /// <summary>
    /// The CommonContainerBuilder implementation for autofac that enables common registration
    /// of types from Mockery
    /// </summary>
    [Export(typeof(ICommonContainerBuilder))]
    public class CommonContainerBuilder : ICommonContainerBuilder
    {
        private readonly ContainerBuilder _containerBuilder;

        /// <summary>
        /// ctor
        /// </summary>
        public CommonContainerBuilder()
        {
            _containerBuilder = new ContainerBuilder();
        }
        
        #region ICommonContainerBuilder Members

        /// <summary>
        /// Register an instance as a singleton for resolution purposes
        /// </summary>
        /// <typeparam name="TType">type of the incoming instance either explicit or implicit</typeparam>
        /// <param name="resolveType">the resolution type</param>
        /// <param name="instance">the instance to be registered</param>
        public void RegisterInstance<TType>(Type resolveType, TType instance)
        {
            _containerBuilder.Register(c => instance).As(resolveType).SingleInstance();
        }

        /// <summary>
        /// Registers a type as a singleton instance for resolution purposes
        /// </summary>
        /// <typeparam name="TType">the type to be instantiated on resolve</typeparam>
        /// <typeparam name="TResolveType">the type to be used for resolving</typeparam>
        public void RegisterType<TType, TResolveType>() where TType : TResolveType
        {
            _containerBuilder.RegisterType<TType>().As<TResolveType>().SingleInstance();
        }

        /// <summary>
        /// Registers a type as a singleton instance for resolution purposes under the
        /// same type name
        /// </summary>
        /// <typeparam name="TType">type being registered with Ioc container</typeparam>
        public void RegisterType<TType>()
        {
            _containerBuilder.RegisterType<TType>().SingleInstance();
        }

        private IServiceLocator _serviceLocator;
        /// <summary>
        /// Creates a service locator implemented as a CommonServiceLocator implementation
        /// </summary>
        /// <returns>IServiceLocator instance</returns>
        public IServiceLocator ServiceLocator
        {
            get
            {
                if( _serviceLocator == null)
                    _serviceLocator = new AutofacServiceLocator(_containerBuilder.Build());

                return _serviceLocator;
            }
        }


        /// <summary>
        /// returns a new instance of the Common Container Builder to support a new
        /// process.  This is used to eliminate time to locate the container builder.
        /// </summary>
        /// <returns></returns>
        public ICommonContainerBuilder New()
        {
            return new CommonContainerBuilder();
        }

        #endregion
    }
}
